package com.open.basic.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;


/**
 * @author system
 * @Date 2023/12/3 14:49
 * @description 线程池工具类，可以实现MDC传递
 */
@Slf4j
public class ThreadPoolUtil {

    private static final Map<String, ThreadPoolExecutor> EXECUTOR_MAP = new ConcurrentHashMap<>();

    /**
     * 核心线程池大小
     */
    private static int corePoolSize = 10;


    /**
     * 最大线程池大小
     */
    private static int maximumPoolSize = 20;

    // 空闲线程保留时间60秒
    private static int keepAliveTime = 60;

    // 队列容量为1000
    private static int queueCapacity = 1000;

    private static final SystemThreadFactory BATTER_THREAD_FACTORY = new SystemThreadFactory("default-pool");

    private static final ThreadPoolExecutor DEFAULT_THREAD_POOL = new ThreadMdcUtil.ThreadPoolExecutorMdcWrapper(corePoolSize, maximumPoolSize, keepAliveTime,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>(queueCapacity), BATTER_THREAD_FACTORY, new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 获取默认线程池
     */
    public static ThreadPoolExecutor getDefaultThreadPool() {
        return DEFAULT_THREAD_POOL;
    }


    /**
     * 获取新线程池
     *
     * @param corePoolSize 核心线程池
     * @param name         线程池名称
     * @return
     */
    public static synchronized ThreadPoolExecutor getNewThreadPool(String name, int corePoolSize) {
        if (EXECUTOR_MAP.containsKey(name)) {
            return EXECUTOR_MAP.get(name);
        }
        SystemThreadFactory systemThreadFactory = new SystemThreadFactory(name);
        ThreadMdcUtil.ThreadPoolExecutorMdcWrapper threadPoolExecutorMdcWrapper = new ThreadMdcUtil.ThreadPoolExecutorMdcWrapper(corePoolSize, corePoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(queueCapacity), systemThreadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
        EXECUTOR_MAP.put(name, threadPoolExecutorMdcWrapper);
        return threadPoolExecutorMdcWrapper;
    }

    public static void execute(Runnable runnable) {
        DEFAULT_THREAD_POOL.execute(runnable);
    }

    public static Future<?> submit(Runnable runnable) {
        return DEFAULT_THREAD_POOL.submit(runnable);
    }


    /**
     * 回收线程资源
     *
     * @param poolExecutor
     */
    public static void releaseThreadPoolExecutor(ThreadPoolExecutor poolExecutor) {
        if (poolExecutor != null) {
            poolExecutor.shutdown();
        }
    }

    /**
     * 回收线程资源
     *
     * @param poolName
     */
    public static void releaseThreadPoolExecutor(String poolName) {
        if (poolName == null || Objects.equals(poolName, "")) return;
        ThreadPoolExecutor threadPoolExecutor = EXECUTOR_MAP.remove(poolName);
        if (threadPoolExecutor != null) {
            releaseThreadPoolExecutor(threadPoolExecutor);
        }
    }

}
